// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	8/2/2013 7:08:34 PM				
// -----------------------------

#include "Lua.h"
#include "LuaError.h"
#include "LuaIncl.h"
#include "LuaStackGuard.h"
#include "LuaStack.h"
#include "LuaTable.h"
#include "LuaStackDump.h"

#include <string>

namespace ObjectLua
{

	int luaPanic(lua_State* lpState)
	{
		LuaError::handleError(lpState);
		return 0;
	}

	Lua::Lua()
		: m_lpState(nullptr)
		, m_lpGlobalTable(new LuaTable(this,LUA_RIDX_GLOBALS))
		, m_lpStack(new LuaStack(this))
	{
		m_lpState = luaL_newstate();
		luaL_openlibs(m_lpState);
		lua_atpanic(m_lpState,luaPanic);

		LuaStackDump::s_lpLua = this;
	}
	
	Lua::~Lua()
	{
		delete m_lpGlobalTable;
		delete m_lpStack;

		if(m_lpState)
			lua_close(m_lpState);
		m_lpState = nullptr;
	}

	void Lua::pushError(const char* lpMsg)
	{
		luaL_error(m_lpState, lpMsg);
	}

	void Lua::runFile(const char* lpFile)
	{
		LUA_ASSERT(lpFile);
		LuaStackGuard stackGuard(this);

		int iResult = luaL_dofile(m_lpState,lpFile);
		if(iResult != 0)
			LuaError::handleError(m_lpState);
	}

	void Lua::addPath(const char* lpPath)
	{
		LUA_ASSERT(lpPath);
		LuaStackGuard stackGuard(this);

		lua_getglobal(m_lpState, "package");
		lua_getfield(m_lpState, -1, "path");
		const char* lpOldPath = lua_tostring(m_lpState, -1);

		const char* lpSuffix = "\?.lua";
		size_t pathLen = strnlen_s(lpPath, 512) + 1;
		size_t newLen = strnlen_s(lpOldPath, 512) + strnlen_s(lpSuffix, 512) + strnlen_s(lpPath, 512) + 2;
		if(lpPath[pathLen - 2] != '\\')
			newLen += 1;
		char* lpNewPath = new char[newLen];
		sprintf_s(lpNewPath, newLen, "%s%s%s", lpOldPath, ";", lpPath);
		if(lpPath[pathLen - 2] != '\\')
			sprintf_s(lpNewPath, newLen, "%s%s%s", lpNewPath, "\\", lpSuffix);
		else
			sprintf_s(lpNewPath, newLen, "%s%s", lpNewPath, lpSuffix);

		lua_pop(m_lpState, 1);
		lua_pushstring(m_lpState, lpNewPath);
		lua_setfield(m_lpState, -2, "path");
		lua_pop(m_lpState, 1);

		delete[] lpNewPath;
	}

	LuaTable* Lua::getGlobals()
	{
		return m_lpGlobalTable;
	}
	LuaStack* Lua::getStack()
	{
		return m_lpStack;
	}

	lua_State* Lua::getState() const
	{
		return m_lpState;
	}

}